﻿using Microsoft.Win32;
using System;
using System.Net;

namespace _12306Bot.Common
{
    public class OrderLimit
    {
        private static RegistryKey rkMain = Registry.LocalMachine.OpenSubKey(@"Software", true);
        private static RegistryKey rkCheck = Registry.Users.OpenSubKey(@".DEFAULT\Software", true);

        private static String strMainSubKey = "12306BOT";
        private static String strCheckSubKey = "NoteTake";

        private static String strMainValueKey = "MyLove";
        private static String strCheckValueKey = "MyBaby";

        //限订张数
        public static readonly int iMaxOrderCount = 15;
        //回溯时长，在此时间范围内限订iMaxOrderCount张
        public static readonly long lOrderCheckPeriod = 96 * 60 * 60 * 10000000L;//单位：100毫微秒

        /// <summary>
        /// 连接
        /// </summary>
        public static WebBot wbOrderLimitLink;

        /// <summary>
        /// 检查注册表
        /// </summary>
        /// <param name="strFirstOrderDateTime">返回最早的订票时间</param>
        /// <returns>-1：恶意修改注册表；0：超过限制；1：可以订票</returns>
        public static int LimitCheck(out String strFirstOrderDateTime)
        {
            strFirstOrderDateTime = "";

            //删了主键值，没删检查键值
            if ((rkMain.OpenSubKey(strMainSubKey) == null) && (rkCheck.OpenSubKey(strCheckSubKey) != null))
            {
                return -1;
            }

            if (rkMain.OpenSubKey(strMainSubKey) == null)
            {
                rkMain.CreateSubKey(strMainSubKey);
            }
            if (rkCheck.OpenSubKey(strCheckSubKey) == null)
            {
                rkCheck.CreateSubKey(strCheckSubKey);
            }
            //删了主键值，没删检查键值
            if ((rkMain.OpenSubKey(strMainSubKey).GetValue(strMainValueKey) == null) && (rkCheck.OpenSubKey(strCheckSubKey).GetValue(strCheckValueKey) != null))
            {
                return -1;
            }

            if (rkMain.OpenSubKey(strMainSubKey).GetValue(strMainValueKey) == null)
            {
                rkMain.OpenSubKey(strMainSubKey, true).SetValue(strMainValueKey, "");
            }
            if (rkCheck.OpenSubKey(strCheckSubKey).GetValue(strCheckValueKey) == null)
            {
                rkCheck.OpenSubKey(strCheckSubKey, true).SetValue(strCheckValueKey, "");
            }

            String strTicketOrderInfoFromReg = rkMain.OpenSubKey(strMainSubKey).GetValue(strMainValueKey).ToString();
            String strTicketOrderFakeInfoFromReg = rkCheck.OpenSubKey(strCheckSubKey).GetValue(strCheckValueKey).ToString();
                        
            //解密一次验证码
            strTicketOrderFakeInfoFromReg = DES.DecryptDES(strTicketOrderFakeInfoFromReg, DES.strDESKey);
            //验证失败
            if (strTicketOrderInfoFromReg != strTicketOrderFakeInfoFromReg)
            {
                return -1;
            }
            //解密订票信息
            strTicketOrderInfoFromReg = DES.DecryptDES(strTicketOrderInfoFromReg, DES.strDESKey);
            if (strTicketOrderInfoFromReg == "")
            {
                return iMaxOrderCount;
            }

            String[] strArrTicketOrderInfo = strTicketOrderInfoFromReg.Split('|');
            //为了用户体验，不可以简单判断订票队列是否已满，还是要判断每张票的时间
            //if (strArrTicketOrderInfo.Length < iMaxOrderCount)
            //{
            //    //返回剩余张数限制
            //    return iMaxOrderCount - strArrTicketOrderInfo.Length;
            //}

            //随便发一条，获取服务器时间
            wbOrderLimitLink.SendData((HttpWebRequest)WebRequest.Create(new Uri(wbOrderLimitLink.uriBase, "otsweb/loginAction.do?method=login")));

            String strTicketOrderInfoToReg = "";
            for (int i = 0; i < strArrTicketOrderInfo.Length; i++)
            {
                //对已订票信息进行整理，超出时间的票务信息就不要了
                if (wbOrderLimitLink.DteServer.Ticks - Convert.ToInt64(strArrTicketOrderInfo[i]) < lOrderCheckPeriod)
                {
                    if (strTicketOrderInfoToReg == "")
                    {
                        strTicketOrderInfoToReg = strArrTicketOrderInfo[i];
                        //第一个时间就是最早的订票时间
                        strFirstOrderDateTime = (new DateTime(Convert.ToInt64(strTicketOrderInfoToReg))).ToString();
                    }
                    else
                    {
                        strTicketOrderInfoToReg += "|" + strArrTicketOrderInfo[i];
                    }
                }
            }

            //剩余张数
            int iRemainCount;
            if (strTicketOrderInfoToReg == "")
            {
                iRemainCount = iMaxOrderCount;
            }
            else
            {
                iRemainCount = iMaxOrderCount - strTicketOrderInfoToReg.Split('|').Length;
            }

            //如果所有已订的票都在时间范围内并且已订票数量已满，则不能再订票了
            if ((strTicketOrderInfoToReg == strTicketOrderInfoFromReg) && (strArrTicketOrderInfo.Length >= iMaxOrderCount))
            {
                return 0;
            }
            else
            {
                //订票信息
                rkMain.OpenSubKey(strMainSubKey, true).SetValue(strMainValueKey, DES.EncryptDES(strTicketOrderInfoToReg, DES.strDESKey));
                //验证信息
                rkCheck.OpenSubKey(strCheckSubKey, true).SetValue(strCheckValueKey, DES.EncryptDES(DES.EncryptDES(strTicketOrderInfoToReg, DES.strDESKey), DES.strDESKey));

                //返回剩余张数限制
                return iRemainCount;
            }
        }

        public static void SetCheck(int TicketCount)
        {
            //随便发一条，获取服务器时间
            wbOrderLimitLink.SendData((HttpWebRequest)WebRequest.Create(new Uri(wbOrderLimitLink.uriBase, "otsweb/loginAction.do?method=login")));
            //不做项检查，出错就让它去
            String strTicketOrderInfo = rkMain.OpenSubKey(strMainSubKey).GetValue(strMainValueKey).ToString();
            //解密
            strTicketOrderInfo = DES.DecryptDES(strTicketOrderInfo, DES.strDESKey);

            //验证用数据
            String strTicketOrderFakeInfo = "";

            for (int i = 0; i < TicketCount; i++)
            {
                if (strTicketOrderInfo == "")
                {
                    strTicketOrderInfo = wbOrderLimitLink.DteServer.Ticks.ToString();
                }
                else
                {
                    strTicketOrderInfo += "|" + wbOrderLimitLink.DteServer.Ticks.ToString();
                }
            }
            //加密
            strTicketOrderInfo = DES.EncryptDES(strTicketOrderInfo, DES.strDESKey);
            //验证数据二重加密
            strTicketOrderFakeInfo = DES.EncryptDES(strTicketOrderInfo, DES.strDESKey);

            rkMain.OpenSubKey(strMainSubKey, true).SetValue(strMainValueKey, strTicketOrderInfo);
            rkCheck.OpenSubKey(strCheckSubKey, true).SetValue(strCheckValueKey, strTicketOrderFakeInfo);
        }
    }
}
